{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Info Extraction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "it's much more easier to extract information of model from pytorch module than onnx...onnx doesn't have output shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "graph torch-jit-export (\n",
      "  %1[FLOAT, 1x3x224x224]\n",
      ") initializers (\n",
      "  %2[FLOAT, 64x3x3x3]\n",
      "  %3[FLOAT, 64]\n",
      "  %4[FLOAT, 64x64x3x3]\n",
      "  %5[FLOAT, 64]\n",
      "  %6[FLOAT, 128x64x3x3]\n",
      "  %7[FLOAT, 128]\n",
      "  %8[FLOAT, 128x128x3x3]\n",
      "  %9[FLOAT, 128]\n",
      "  %10[FLOAT, 256x128x3x3]\n",
      "  %11[FLOAT, 256]\n",
      "  %12[FLOAT, 256x256x3x3]\n",
      "  %13[FLOAT, 256]\n",
      "  %14[FLOAT, 256x256x3x3]\n",
      "  %15[FLOAT, 256]\n",
      "  %16[FLOAT, 256x256x3x3]\n",
      "  %17[FLOAT, 256]\n",
      "  %18[FLOAT, 512x256x3x3]\n",
      "  %19[FLOAT, 512]\n",
      "  %20[FLOAT, 512x512x3x3]\n",
      "  %21[FLOAT, 512]\n",
      "  %22[FLOAT, 512x512x3x3]\n",
      "  %23[FLOAT, 512]\n",
      "  %24[FLOAT, 512x512x3x3]\n",
      "  %25[FLOAT, 512]\n",
      "  %26[FLOAT, 512x512x3x3]\n",
      "  %27[FLOAT, 512]\n",
      "  %28[FLOAT, 512x512x3x3]\n",
      "  %29[FLOAT, 512]\n",
      "  %30[FLOAT, 512x512x3x3]\n",
      "  %31[FLOAT, 512]\n",
      "  %32[FLOAT, 512x512x3x3]\n",
      "  %33[FLOAT, 512]\n",
      "  %34[FLOAT, 4096x25088]\n",
      "  %35[FLOAT, 4096]\n",
      "  %36[FLOAT, 4096x4096]\n",
      "  %37[FLOAT, 4096]\n",
      "  %38[FLOAT, 1000x4096]\n",
      "  %39[FLOAT, 1000]\n",
      ") {\n",
      "  %41 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%1, %2)\n",
      "  %42 = Add[axis = 1, broadcast = 1](%41, %3)\n",
      "  %43 = Relu(%42)\n",
      "  %45 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%43, %4)\n",
      "  %46 = Add[axis = 1, broadcast = 1](%45, %5)\n",
      "  %47 = Relu(%46)\n",
      "  %48 = MaxPool[kernel_shape = [2, 2], pads = [0, 0], strides = [2, 2]](%47)\n",
      "  %50 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%48, %6)\n",
      "  %51 = Add[axis = 1, broadcast = 1](%50, %7)\n",
      "  %52 = Relu(%51)\n",
      "  %54 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%52, %8)\n",
      "  %55 = Add[axis = 1, broadcast = 1](%54, %9)\n",
      "  %56 = Relu(%55)\n",
      "  %57 = MaxPool[kernel_shape = [2, 2], pads = [0, 0], strides = [2, 2]](%56)\n",
      "  %59 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%57, %10)\n",
      "  %60 = Add[axis = 1, broadcast = 1](%59, %11)\n",
      "  %61 = Relu(%60)\n",
      "  %63 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%61, %12)\n",
      "  %64 = Add[axis = 1, broadcast = 1](%63, %13)\n",
      "  %65 = Relu(%64)\n",
      "  %67 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%65, %14)\n",
      "  %68 = Add[axis = 1, broadcast = 1](%67, %15)\n",
      "  %69 = Relu(%68)\n",
      "  %71 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%69, %16)\n",
      "  %72 = Add[axis = 1, broadcast = 1](%71, %17)\n",
      "  %73 = Relu(%72)\n",
      "  %74 = MaxPool[kernel_shape = [2, 2], pads = [0, 0], strides = [2, 2]](%73)\n",
      "  %76 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%74, %18)\n",
      "  %77 = Add[axis = 1, broadcast = 1](%76, %19)\n",
      "  %78 = Relu(%77)\n",
      "  %80 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%78, %20)\n",
      "  %81 = Add[axis = 1, broadcast = 1](%80, %21)\n",
      "  %82 = Relu(%81)\n",
      "  %84 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%82, %22)\n",
      "  %85 = Add[axis = 1, broadcast = 1](%84, %23)\n",
      "  %86 = Relu(%85)\n",
      "  %88 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%86, %24)\n",
      "  %89 = Add[axis = 1, broadcast = 1](%88, %25)\n",
      "  %90 = Relu(%89)\n",
      "  %91 = MaxPool[kernel_shape = [2, 2], pads = [0, 0], strides = [2, 2]](%90)\n",
      "  %93 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%91, %26)\n",
      "  %94 = Add[axis = 1, broadcast = 1](%93, %27)\n",
      "  %95 = Relu(%94)\n",
      "  %97 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%95, %28)\n",
      "  %98 = Add[axis = 1, broadcast = 1](%97, %29)\n",
      "  %99 = Relu(%98)\n",
      "  %101 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%99, %30)\n",
      "  %102 = Add[axis = 1, broadcast = 1](%101, %31)\n",
      "  %103 = Relu(%102)\n",
      "  %105 = Conv[dilations = [1, 1], group = 1, kernel_shape = [3, 3], pads = [1, 1, 1, 1], strides = [1, 1]](%103, %32)\n",
      "  %106 = Add[axis = 1, broadcast = 1](%105, %33)\n",
      "  %107 = Relu(%106)\n",
      "  %108 = MaxPool[kernel_shape = [2, 2], pads = [0, 0], strides = [2, 2]](%107)\n",
      "  %109 = Reshape[shape = [1, -1]](%108)\n",
      "  %112 = Gemm[alpha = 1, beta = 1, broadcast = 1, transB = 1](%109, %34, %35)\n",
      "  %113 = Relu(%112)\n",
      "  %115, %116 = Dropout[is_test = 1, ratio = 0.5](%113)\n",
      "  %119 = Gemm[alpha = 1, beta = 1, broadcast = 1, transB = 1](%115, %36, %37)\n",
      "  %120 = Relu(%119)\n",
      "  %122, %123 = Dropout[is_test = 1, ratio = 0.5](%120)\n",
      "  %126 = Gemm[alpha = 1, beta = 1, broadcast = 1, transB = 1](%122, %38, %39)\n",
      "  return %126\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "import onnx\n",
    "\n",
    "# Load the ONNX model\n",
    "model = onnx.load(\"onnx/vgg19.onnx\")\n",
    "\n",
    "# Check that the IR is well formed\n",
    "onnx.checker.check_model(model)\n",
    "\n",
    "# Print a human readable representation of the graph\n",
    "print(onnx.helper.printable_graph(model.graph))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python2.7/dist-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n"
     ]
    }
   ],
   "source": [
    "#import onnx_caffe2.backend as backend\n",
    "import onnx_tf.backend as backend\n",
    "import numpy as np\n",
    "import time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Find Graph Edge (each link)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Node is operation, start from 0 ; Entity is object, start from u'1' (means %1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "基本上把每個node跑過一次後，所有的Entity都會摸到"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_graph_order():\n",
    "    Node2nextEntity = {}\n",
    "    Entity2nextNode = {} \n",
    "    for Node_idx, node in enumerate(model.graph.node):\n",
    "        # node input\n",
    "        for Entity_idx in node.input:\n",
    "            if not Entity_idx in Entity2nextNode.keys():\n",
    "                Entity2nextNode.update({Entity_idx:Node_idx})\n",
    "        # node output\n",
    "        for Entity_idx in node.output:\n",
    "            if not Node_idx in Node2nextEntity.keys():\n",
    "                Node2nextEntity.update({Node_idx:Entity_idx})                \n",
    "    return Node2nextEntity, Entity2nextNode\n",
    "      \n",
    "Node2nextEntity, Entity2nextNode = get_graph_order()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(61, 99)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(Node2nextEntity), len(Entity2nextNode)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "pickle.dump(Node2nextEntity,open('onnx/vgg19_Node2nextEntity_dict.pkl','wb'))\n",
    "pickle.dump(Entity2nextNode,open('onnx/vgg19_Entity2nextNode_dict.pkl','wb'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get Subgroup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "Node2nextEntity = pickle.load(open('onnx/vgg19_Node2nextEntity_dict.pkl','rb'))\n",
    "Entity2nextNode = pickle.load(open('onnx/vgg19_Entity2nextNode_dict.pkl','rb'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "node[0] ...\n",
      "node[0] fit op_type [Conv]\n",
      "node[1] fit op_type [Add]\n",
      "node[2] fit op_type [Relu]\n",
      "node[0] ...fit!\n",
      "\n",
      "node[1] ...\n",
      "node[1] doesn't fit op_type [Conv]\n",
      "node[1] ...NOT fit!\n",
      "\n",
      "node[2] ...\n",
      "node[2] doesn't fit op_type [Conv]\n",
      "node[2] ...NOT fit!\n",
      "\n",
      "node[3] ...\n",
      "node[3] fit op_type [Conv]\n",
      "node[4] fit op_type [Add]\n",
      "node[5] fit op_type [Relu]\n",
      "node[3] ...fit!\n",
      "\n",
      "node[4] ...\n",
      "node[4] doesn't fit op_type [Conv]\n",
      "node[4] ...NOT fit!\n",
      "\n",
      "node[5] ...\n",
      "node[5] doesn't fit op_type [Conv]\n",
      "node[5] ...NOT fit!\n",
      "\n",
      "node[6] ...\n",
      "node[6] doesn't fit op_type [Conv]\n",
      "node[6] ...NOT fit!\n",
      "\n",
      "node[7] ...\n",
      "node[7] fit op_type [Conv]\n",
      "node[8] fit op_type [Add]\n",
      "node[9] fit op_type [Relu]\n",
      "node[7] ...fit!\n",
      "\n",
      "node[8] ...\n",
      "node[8] doesn't fit op_type [Conv]\n",
      "node[8] ...NOT fit!\n",
      "\n",
      "node[9] ...\n",
      "node[9] doesn't fit op_type [Conv]\n",
      "node[9] ...NOT fit!\n",
      "\n",
      "node[10] ...\n",
      "node[10] fit op_type [Conv]\n",
      "node[11] fit op_type [Add]\n",
      "node[12] fit op_type [Relu]\n",
      "node[10] ...fit!\n",
      "\n",
      "node[11] ...\n",
      "node[11] doesn't fit op_type [Conv]\n",
      "node[11] ...NOT fit!\n",
      "\n",
      "node[12] ...\n",
      "node[12] doesn't fit op_type [Conv]\n",
      "node[12] ...NOT fit!\n",
      "\n",
      "node[13] ...\n",
      "node[13] doesn't fit op_type [Conv]\n",
      "node[13] ...NOT fit!\n",
      "\n",
      "node[14] ...\n",
      "node[14] fit op_type [Conv]\n",
      "node[15] fit op_type [Add]\n",
      "node[16] fit op_type [Relu]\n",
      "node[14] ...fit!\n",
      "\n",
      "node[15] ...\n",
      "node[15] doesn't fit op_type [Conv]\n",
      "node[15] ...NOT fit!\n",
      "\n",
      "node[16] ...\n",
      "node[16] doesn't fit op_type [Conv]\n",
      "node[16] ...NOT fit!\n",
      "\n",
      "node[17] ...\n",
      "node[17] fit op_type [Conv]\n",
      "node[18] fit op_type [Add]\n",
      "node[19] fit op_type [Relu]\n",
      "node[17] ...fit!\n",
      "\n",
      "node[18] ...\n",
      "node[18] doesn't fit op_type [Conv]\n",
      "node[18] ...NOT fit!\n",
      "\n",
      "node[19] ...\n",
      "node[19] doesn't fit op_type [Conv]\n",
      "node[19] ...NOT fit!\n",
      "\n",
      "node[20] ...\n",
      "node[20] fit op_type [Conv]\n",
      "node[21] fit op_type [Add]\n",
      "node[22] fit op_type [Relu]\n",
      "node[20] ...fit!\n",
      "\n",
      "node[21] ...\n",
      "node[21] doesn't fit op_type [Conv]\n",
      "node[21] ...NOT fit!\n",
      "\n",
      "node[22] ...\n",
      "node[22] doesn't fit op_type [Conv]\n",
      "node[22] ...NOT fit!\n",
      "\n",
      "node[23] ...\n",
      "node[23] fit op_type [Conv]\n",
      "node[24] fit op_type [Add]\n",
      "node[25] fit op_type [Relu]\n",
      "node[23] ...fit!\n",
      "\n",
      "node[24] ...\n",
      "node[24] doesn't fit op_type [Conv]\n",
      "node[24] ...NOT fit!\n",
      "\n",
      "node[25] ...\n",
      "node[25] doesn't fit op_type [Conv]\n",
      "node[25] ...NOT fit!\n",
      "\n",
      "node[26] ...\n",
      "node[26] doesn't fit op_type [Conv]\n",
      "node[26] ...NOT fit!\n",
      "\n",
      "node[27] ...\n",
      "node[27] fit op_type [Conv]\n",
      "node[28] fit op_type [Add]\n",
      "node[29] fit op_type [Relu]\n",
      "node[27] ...fit!\n",
      "\n",
      "node[28] ...\n",
      "node[28] doesn't fit op_type [Conv]\n",
      "node[28] ...NOT fit!\n",
      "\n",
      "node[29] ...\n",
      "node[29] doesn't fit op_type [Conv]\n",
      "node[29] ...NOT fit!\n",
      "\n",
      "node[30] ...\n",
      "node[30] fit op_type [Conv]\n",
      "node[31] fit op_type [Add]\n",
      "node[32] fit op_type [Relu]\n",
      "node[30] ...fit!\n",
      "\n",
      "node[31] ...\n",
      "node[31] doesn't fit op_type [Conv]\n",
      "node[31] ...NOT fit!\n",
      "\n",
      "node[32] ...\n",
      "node[32] doesn't fit op_type [Conv]\n",
      "node[32] ...NOT fit!\n",
      "\n",
      "node[33] ...\n",
      "node[33] fit op_type [Conv]\n",
      "node[34] fit op_type [Add]\n",
      "node[35] fit op_type [Relu]\n",
      "node[33] ...fit!\n",
      "\n",
      "node[34] ...\n",
      "node[34] doesn't fit op_type [Conv]\n",
      "node[34] ...NOT fit!\n",
      "\n",
      "node[35] ...\n",
      "node[35] doesn't fit op_type [Conv]\n",
      "node[35] ...NOT fit!\n",
      "\n",
      "node[36] ...\n",
      "node[36] fit op_type [Conv]\n",
      "node[37] fit op_type [Add]\n",
      "node[38] fit op_type [Relu]\n",
      "node[36] ...fit!\n",
      "\n",
      "node[37] ...\n",
      "node[37] doesn't fit op_type [Conv]\n",
      "node[37] ...NOT fit!\n",
      "\n",
      "node[38] ...\n",
      "node[38] doesn't fit op_type [Conv]\n",
      "node[38] ...NOT fit!\n",
      "\n",
      "node[39] ...\n",
      "node[39] doesn't fit op_type [Conv]\n",
      "node[39] ...NOT fit!\n",
      "\n",
      "node[40] ...\n",
      "node[40] fit op_type [Conv]\n",
      "node[41] fit op_type [Add]\n",
      "node[42] fit op_type [Relu]\n",
      "node[40] ...fit!\n",
      "\n",
      "node[41] ...\n",
      "node[41] doesn't fit op_type [Conv]\n",
      "node[41] ...NOT fit!\n",
      "\n",
      "node[42] ...\n",
      "node[42] doesn't fit op_type [Conv]\n",
      "node[42] ...NOT fit!\n",
      "\n",
      "node[43] ...\n",
      "node[43] fit op_type [Conv]\n",
      "node[44] fit op_type [Add]\n",
      "node[45] fit op_type [Relu]\n",
      "node[43] ...fit!\n",
      "\n",
      "node[44] ...\n",
      "node[44] doesn't fit op_type [Conv]\n",
      "node[44] ...NOT fit!\n",
      "\n",
      "node[45] ...\n",
      "node[45] doesn't fit op_type [Conv]\n",
      "node[45] ...NOT fit!\n",
      "\n",
      "node[46] ...\n",
      "node[46] fit op_type [Conv]\n",
      "node[47] fit op_type [Add]\n",
      "node[48] fit op_type [Relu]\n",
      "node[46] ...fit!\n",
      "\n",
      "node[47] ...\n",
      "node[47] doesn't fit op_type [Conv]\n",
      "node[47] ...NOT fit!\n",
      "\n",
      "node[48] ...\n",
      "node[48] doesn't fit op_type [Conv]\n",
      "node[48] ...NOT fit!\n",
      "\n",
      "node[49] ...\n",
      "node[49] fit op_type [Conv]\n",
      "node[50] fit op_type [Add]\n",
      "node[51] fit op_type [Relu]\n",
      "node[49] ...fit!\n",
      "\n",
      "node[50] ...\n",
      "node[50] doesn't fit op_type [Conv]\n",
      "node[50] ...NOT fit!\n",
      "\n",
      "node[51] ...\n",
      "node[51] doesn't fit op_type [Conv]\n",
      "node[51] ...NOT fit!\n",
      "\n",
      "node[52] ...\n",
      "node[52] doesn't fit op_type [Conv]\n",
      "node[52] ...NOT fit!\n",
      "\n",
      "node[53] ...\n",
      "node[53] doesn't fit op_type [Conv]\n",
      "node[53] ...NOT fit!\n",
      "\n",
      "node[54] ...\n",
      "node[54] doesn't fit op_type [Conv]\n",
      "node[54] ...NOT fit!\n",
      "\n",
      "node[55] ...\n",
      "node[55] doesn't fit op_type [Conv]\n",
      "node[55] ...NOT fit!\n",
      "\n",
      "node[56] ...\n",
      "node[56] doesn't fit op_type [Conv]\n",
      "node[56] ...NOT fit!\n",
      "\n",
      "node[57] ...\n",
      "node[57] doesn't fit op_type [Conv]\n",
      "node[57] ...NOT fit!\n",
      "\n",
      "node[58] ...\n",
      "node[58] doesn't fit op_type [Conv]\n",
      "node[58] ...NOT fit!\n",
      "\n",
      "node[59] ...\n",
      "node[59] doesn't fit op_type [Conv]\n",
      "node[59] ...NOT fit!\n",
      "\n",
      "node[60] ...\n",
      "node[60] doesn't fit op_type [Conv]\n",
      "node[60] ...NOT fit!\n",
      "\n",
      "Node[0, 3, 7, 10, 14, 17, 20, 23, 27, 30, 33, 36, 40, 43, 46, 49] fit the matching pattern\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[3, 10, 23, 36, 49]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def find_sequencial_nodes(search_target=['Conv', 'Add', 'Relu', 'MaxPool'], if_print = False): \n",
    "    found_nodes = []\n",
    "    for i, node in enumerate(model.graph.node): \n",
    "        if if_print: print(\"\\nnode[{}] ...\".format(i))\n",
    "        n_idx = i #init\n",
    "        is_fit = True\n",
    "        for tar in search_target:\n",
    "            try:\n",
    "                assert model.graph.node[n_idx].op_type == tar #check this node\n",
    "                if if_print: print(\"node[{}] fit op_type [{}]\".format(n_idx, tar))\n",
    "                e_idx = Node2nextEntity[n_idx] #find next Entity\n",
    "                n_idx = Entity2nextNode[e_idx] #find next Node\n",
    "                #if if_print: print(e_idx,n_idx)\n",
    "            except: \n",
    "                is_fit = False\n",
    "                if if_print: print(\"node[{}] doesn't fit op_type [{}]\".format(n_idx, tar))\n",
    "                break\n",
    "\n",
    "        if is_fit:\n",
    "            if if_print: print(\"node[{}] ...fit!\".format(i))\n",
    "            found_nodes.append(i)\n",
    "        else:\n",
    "            if if_print: print(\"node[{}] ...NOT fit!\".format(i))\n",
    "    if if_print: print(\"\\nNode{} fit the matching pattern\".format(found_nodes))\n",
    "    return found_nodes\n",
    "find_sequencial_nodes(search_target=['Conv', 'Add', 'Relu'], if_print = True)\n",
    "find_sequencial_nodes(search_target=['Conv', 'Add', 'Relu', 'MaxPool'], if_print = False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "import itertools\n",
    "def get_permutations(a):\n",
    "    p = []\n",
    "    for r in range(len(a)+1):\n",
    "        c = list(itertools.combinations(a,r))\n",
    "        \n",
    "        for cc in c:\n",
    "            p += list(itertools.permutations(cc))\n",
    "    return p \n",
    "#a = [4,5,6]\n",
    "#get_permutations(a)    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[['Conv'],\n",
       " ['Conv', 'Add'],\n",
       " ['Conv', 'Relu'],\n",
       " ['Conv', 'MaxPool'],\n",
       " ['Conv', 'Add', 'Relu'],\n",
       " ['Conv', 'Relu', 'Add'],\n",
       " ['Conv', 'Add', 'MaxPool'],\n",
       " ['Conv', 'MaxPool', 'Add'],\n",
       " ['Conv', 'Relu', 'MaxPool'],\n",
       " ['Conv', 'MaxPool', 'Relu'],\n",
       " ['Conv', 'Add', 'Relu', 'MaxPool'],\n",
       " ['Conv', 'Add', 'MaxPool', 'Relu'],\n",
       " ['Conv', 'Relu', 'Add', 'MaxPool'],\n",
       " ['Conv', 'Relu', 'MaxPool', 'Add'],\n",
       " ['Conv', 'MaxPool', 'Add', 'Relu'],\n",
       " ['Conv', 'MaxPool', 'Relu', 'Add']]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "search_head = ['Conv']\n",
    "followings = ['Add', 'Relu', 'MaxPool']\n",
    "search_targets = [ search_head+list(foll) for foll in get_permutations(followings)] \n",
    "search_targets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "search:['Conv'], \n",
      "get matching node:[0, 3, 7, 10, 14, 17, 20, 23, 27, 30, 33, 36, 40, 43, 46, 49]\n",
      "\n",
      "search:['Conv', 'Add'], \n",
      "get matching node:[0, 3, 7, 10, 14, 17, 20, 23, 27, 30, 33, 36, 40, 43, 46, 49]\n",
      "\n",
      "search:['Conv', 'Add', 'Relu'], \n",
      "get matching node:[0, 3, 7, 10, 14, 17, 20, 23, 27, 30, 33, 36, 40, 43, 46, 49]\n",
      "\n",
      "search:['Conv', 'Add', 'Relu', 'MaxPool'], \n",
      "get matching node:[3, 10, 23, 36, 49]\n"
     ]
    }
   ],
   "source": [
    "matchings = [find_sequencial_nodes(search_target) for search_target in search_targets]\n",
    "\n",
    "for i,matching in enumerate(matchings):\n",
    "    if matching!=[]:\n",
    "        print(\"\\nsearch:{}, \\nget matching node:{}\".format(search_targets[i],matching))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
